package io.github.luons.mediator.core.utils;

import io.github.luons.mediator.core.spi.result.ResultCode;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * EnumUtils
 *
 * @author : luons
 */
public class EnumUtils {

    /**
     * get ResultCode by code
     *
     * @param clazz clazz
     * @param code  code
     * @param <T>   T
     * @return T
     */
    public static <T extends ResultCode> T getEnumByCode(Class<T> clazz, Integer code) {
        if (code == null) {
            return null;
        }
        for (T e : clazz.getEnumConstants()) {
            if (code.equals(e.getCode())) {
                return e;
            }
        }
        return null;
    }

    /**
     * get ResultCode by Name
     *
     * @param clazz clazz
     * @param name  name
     * @param <T>   T
     * @return T
     */
    public static <T extends ResultCode> T getEnumByName(Class<T> clazz, String name) {
        if (StringUtils.isBlank(name)) {
            return null;
        }
        for (T e : clazz.getEnumConstants()) {
            if (e.getName().equals(name)) {
                return e;
            }
        }
        return null;
    }

    /**
     * get name by code
     *
     * @param clazz clazz
     * @param code  code
     * @return String
     */
    public static String getNameByCode(Class<? extends ResultCode> clazz, Integer code) {
        if (code == null) {
            return "unknown";
        }
        ResultCode resultCode = getEnumByCode(clazz, code);
        if (resultCode == null) {
            return "unknown " + code;
        }
        return resultCode.getName();
    }

    /**
     * get Enum by MethodName
     *
     * @param clazz      clazz
     * @param methodName methodName
     * @param enumValue  enumValue
     * @param <T>        T
     * @return T
     */
    public static <T extends Enum<T>> T getEnumByMethod(Class<T> clazz, String methodName, Object enumValue) {
        T result = null;
        T[] enumConstants = clazz.getEnumConstants();
        try {
            Method method = clazz.getMethod(methodName);
            for (T entry : enumConstants) {
                if (enumValue.equals(method.invoke(entry))) {
                    result = entry;
                    break;
                }
            }
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return result;
    }

}
